using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Linq;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Security;

namespace CP.SharePoint.SiteStyles.Features.Farm
{
    /// <summary>
    /// This class handles events raised during feature activation, deactivation, installation, uninstallation, and upgrade.
    /// </summary>
    /// <remarks>
    /// The GUID attached to this class may be used during packaging and should not be modified.
    /// </remarks>
    [Guid("8cfa9d35-202d-4df4-b8fd-c14f199c80a6")]
    public class FarmEventReceiver : SPFeatureReceiver
    {
        #region Feature Events
        /// <summary>
        /// Event handler that executes whenever the feature is activated
        /// </summary>
        /// <param name="properties">Properties object for the feature and it's parent.</param>
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            try
            {
                // create the site style list
                using (SPSite site = SPAdministrationWebApplication.Local.Sites[0])
                using (SPWeb web = site.OpenWeb())
                {
                    if (!ListExists(web, Resources.ListNameSiteStyles))
                    {
                        CreateSiteStylesList(web);
                    }
                }
            }
            catch (Exception ex)
            {
                SPDiagnosticsService.Local.WriteTrace(0, new SPDiagnosticsCategory("CP.SharePoint.SiteStyles - Farm Feature Activated", TraceSeverity.Unexpected, EventSeverity.Error), TraceSeverity.Unexpected, ex.Message, ex.StackTrace);
            }
        }
        #endregion

        /// <summary>
        /// Checks the given web for the existance of a specific list based on the
        /// title provided.
        /// </summary>
        /// <param name="web">The web to check for the existance of the list.</param>
        /// <param name="title">The title of the list to check for.</param>
        /// <returns>True if the list exists, false otherwise.</returns>
        private bool ListExists(SPWeb web, string title)
        {
            return web.Lists.Cast<SPList>().Any(list => string.Equals(list.Title, title));
        }

        /// <summary>
        /// Creates the site styles list based within the provided web based 
        /// on constants defined in the resources file. The site styles list
        /// allows users to create and manage site styles within Central
        /// Administration.
        /// </summary>
        /// <param name="web">The web that the site styles list should be created in.</param>
        private void CreateSiteStylesList(SPWeb web)
        {
            // create list
            Guid listId = web.Lists.Add(Resources.ListNameSiteStyles, Resources.ListDescriptionSiteStyles, SPListTemplateType.GenericList);
            SPList list = web.Lists[listId];

            // add fields to list
            list.Fields.Add(Resources.FieldNameDescription, SPFieldType.Note, false);
            list.Fields.Add(Resources.FieldNameCssPath, SPFieldType.Text, true);
            list.Fields.Add(Resources.FieldNameThumbnail, SPFieldType.Text, false);
            list.Fields.Add(Resources.FieldNameThemable, SPFieldType.Boolean, false);
            list.Update();

            // update fields
            SPField descField = list.Fields[Resources.FieldNameDescription];
            descField.Description = Resources.FieldDescriptionDescription;
            descField.Update();

            SPField cssPathField = list.Fields[Resources.FieldNameCssPath];
            cssPathField.Description = Resources.FieldDescriptionCssPath;
            cssPathField.Update();

            SPField thumbField = list.Fields[Resources.FieldNameThumbnail];
            thumbField.Description = Resources.FieldDescriptionThumbnail;
            thumbField.Update();

            SPField themeableField = list.Fields[Resources.FieldNameThemable];
            themeableField.Description = Resources.FieldDescriptionThemable;
            themeableField.Update();

            // update view
            SPView view = list.DefaultView;
            view.ViewFields.Add(Resources.FieldNameDescription);
            view.ViewFields.Add(Resources.FieldNameCssPath);
            view.ViewFields.Add(Resources.FieldNameThemable);
            view.Update();

            // add event handlers
            string assembly = Assembly.GetExecutingAssembly().FullName;
            SPEventReceiverDefinition itemAddedDefinition = list.EventReceivers.Add();
            itemAddedDefinition.Name = "StyleItemAdded";
            itemAddedDefinition.Type = SPEventReceiverType.ItemAdded;
            itemAddedDefinition.Assembly = assembly;
            itemAddedDefinition.Class = Resources.SiteStylesListReceiverClass;
            itemAddedDefinition.Synchronization = SPEventReceiverSynchronization.Synchronous;
            itemAddedDefinition.SequenceNumber = 10051;
            itemAddedDefinition.Update();

            SPEventReceiverDefinition itemUpdatedDefinition = list.EventReceivers.Add();
            itemUpdatedDefinition.Name = "StyleItemUpdated";
            itemUpdatedDefinition.Type = SPEventReceiverType.ItemUpdated;
            itemUpdatedDefinition.Assembly = assembly;
            itemUpdatedDefinition.Class = Resources.SiteStylesListReceiverClass;
            itemUpdatedDefinition.Synchronization = SPEventReceiverSynchronization.Synchronous;
            itemUpdatedDefinition.SequenceNumber = 10052;
            itemUpdatedDefinition.Update();

            SPEventReceiverDefinition itemDeletedDefinition = list.EventReceivers.Add();
            itemDeletedDefinition.Name = "StyleItemDeleted";
            itemDeletedDefinition.Type = SPEventReceiverType.ItemDeleted;
            itemDeletedDefinition.Assembly = assembly;
            itemDeletedDefinition.Class = Resources.SiteStylesListReceiverClass;
            itemDeletedDefinition.Synchronization = SPEventReceiverSynchronization.Synchronous;
            itemDeletedDefinition.SequenceNumber = 10053;
            itemDeletedDefinition.Update();
            list.Update();
        }
    }
}
